// 组件显示隐藏
// 组件启用禁用
// 组件必填非必填
import * as Blockly from 'blockly/core'
import { componentFuncConfig, commonConfig } from '../config/component'
import store from '@/store'
import { Message } from 'element-ui'
import { findParentByType, getContextText } from '../utils/block'
import { getAllComponentList } from '../utils/component'

Blockly.Extensions.register('dynamic_component_extension',
  function () {
    var that = this
    const dropdown = new Blockly.FieldDropdown(
      function () {
        var options = []
        const comList = getAllComponentList()
        if (!comList.length) {
          options = [['没有数据', 'noData']]
          return options
        }
        for (var i = 0; i < comList.length; i++) {
          const com = comList[i]
          const label = (com?.modelName) ? (com?.__config?.label) : ''
          var dateString = com.name + label + '（' + com.key + '）'
          options.push([dateString, com.key])
        }
        return options
      })
    if (this.getInput('FUNC_INPUT')) {
      dropdown.setValidator(function (value) {
        if (that.getInput('PARAM_INPUT')) {
          that.removeInput('PARAM_INPUT', true)
        }
        that.removeInput('FUNC_INPUT', true)
        that.appendDummyInput('FUNC_INPUT').appendField('方法')
        that.itemCount_ = 0
        that.updateShape_()
        // that.appendDummyInput('PARAM_INPUT')
        // if (that.getInput('PARAM_INPUT')) {
        //   that.moveInputBefore('FUNC_INPUT', 'PARAM_INPUT')
        // }
        Blockly.Extensions.apply('dynamic_func_extension', that, false)
      })
    }

    this.getInput('COMPONENT_INPUT').appendField(dropdown, 'Component')
  })

Blockly.Extensions.register('dynamic_func_extension',
  function () {
    var that = this
    // const tree = store.getters.getModelTreeList // 大纲树
    // const comList = treeToArray(tree)
    const comList = getAllComponentList()
    const dropdown = new Blockly.FieldDropdown(
      function () {
        var options = []
        // 获取component的选择框的值
        // const list = store.getters.getFormList
        // 获取组件的值，Component extension中的值
        const compVar = that.getFieldValue('Component') // 组件的key
        if (!compVar || compVar === 'noData') {
          options = [['没有数据', 'noData']]
          return options
        }
        const com = comList.find(item => item.key === compVar)
        const comType = com.tagName
        const config = componentFuncConfig[comType] || commonConfig
        for (var i = 0; i < config.length; i++) {
          var item = config[i]
          options.push([`${item.alias}(${item.key})`, item.key])
        }
        return options
      })
    dropdown.setValidator(function (value) {
      const oldValue = that.getFieldValue('Function')
      const compVar = that.getFieldValue('Component') // 组件的key
      const com = comList.find(item => item.key === compVar)
      if (!com) return
      const comType = com.tagName
      const config = componentFuncConfig[comType] // 组件的配置
      const funcConfig = config?.find(item => item.key === value)
      const oldConfig = config?.find(item => item.key === oldValue)
      const hasReturn = funcConfig && !!funcConfig.hasReturn
      const oldHasReturn = oldConfig && !!oldConfig.hasReturn
      if (that?.previousConnection?.targetConnection && hasReturn !== oldHasReturn && oldValue !== value) {
        Message({
          message: '该选项不支持当前连接，前先断开连接再选择',
          type: 'warning'
        })
        return null
      }

      // 参数的判断
      const params = funcConfig?.params || []
      that.params = params
      if (!params?.length) {
        that.itemCount_ = 0
        that.updateShape_()
      } else {
        that.itemCount_ = params.length
        that.updateShape_()
      }
      // // 设置有没有函数体
      if (hasReturn) {
        that.setPreviousStatement(false)
        that.setNextStatement(false)
        that.setOutput(true, null)
      } else {
        that.setOutput(false, null)
        that.setPreviousStatement(true)
        that.setNextStatement(true)
      }
      // that.setStatements_(statement)
    })
    // 生成extension的block
    if (!this.getInput('Function')) {
      this.getInput('FUNC_INPUT')
        .appendField(dropdown, 'Function')
    }
  })

// 1.--------获取组件实例 --- 不用
const componentJson = {
  type: 'component_instance',
  message0: '获取组件实例 %1',
  args0: [
    // 动态生成选项
    {
      'type': 'input_dummy',
      'name': 'COMPONENT_INPUT'
    }
  ],
  extensions: ['dynamic_component_extension'],
  output: 'component_instance',
  style: 'component_blocks',
  tooltip: '',
  helpUrl: ''
}

// 创建积木
Blockly.Blocks['component_instance'] = {
  init: function () {
    this.jsonInit(componentJson)
  }
}

Blockly.JavaScript['component_instance'] = function (block) {
  const compVar = block.getFieldValue('Component')
  const code = `context.getComponent('${compVar}')\n`
  return [code, Blockly.JavaScript.ORDER_COMMA]
}

// 2.----------------组件dispatch------------------ 不用

const dispatchJson = {
  type: 'component_dispatch',
  'message0': 'dispatch调用组件 %1 方法 %2  %3',
  args0: [
    // 动态生成选项
    {
      'type': 'input_dummy',
      'name': 'COMPONENT_INPUT'
    },
    {
      'type': 'input_dummy',
      'name': 'FUNC_INPUT'
    },
    {
      'type': 'input_dummy',
      'name': 'PARAM_INPUT'
    }
  ],
  extensions: ['dynamic_component_extension', 'dynamic_func_extension'],
  // previousStatement: null,
  // nextStatement: null,
  output: null,
  inputsInline: true,
  style: 'component_blocks',
  tooltip: '',
  helpUrl: '',
  mutator: 'component_dispatch_mutator'
}
// 创建积木
Blockly.Blocks['component_dispatch'] = {
  init: function () {
    this.jsonInit(dispatchJson)
  }
}

const mixinObj = {
  /**
   * Create XML to represent number of text inputs.
   * @return {!Element} XML storage element.
   * @this {Blockly.Block}
   */
  mutationToDom: function () {
    var container = Blockly.utils.xml.createElement('mutation')
    container.setAttribute('items', this.itemCount_)
    return container
  },
  /**
   * Parse XML to restore the text inputs.
   * @param {!Element} xmlElement XML storage element.
   * @this {Blockly.Block}
   */
  domToMutation: function (xmlElement) {
    this.itemCount_ = parseInt(xmlElement.getAttribute('items'), 10) || 0
    this.updateShape_()
  },
  // /**
  //  * Populate the mutator's dialog with this block's components.
  //  * @param {!Blockly.Workspace} workspace Mutator's workspace.
  //  * @return {!Blockly.Block} Root block in mutator.
  //  * @this {Blockly.Block}
  //  */
  // decompose: function (workspace) {
  //   console.log('decompose')
  //   var containerBlock = workspace.newBlock('param_create_join_container')
  //   containerBlock.initSvg()
  //   var connection = containerBlock.getInput('STACK').connection
  //   for (var i = 0; i < this.itemCount_; i++) {
  //     var itemBlock = workspace.newBlock('param_create_join_item')
  //     itemBlock.initSvg()
  //     connection.connect(itemBlock.previousConnection)
  //     connection = itemBlock.nextConnection
  //   }
  //   return containerBlock
  // },
  // /**
  //  * Reconfigure this block based on the mutator dialog's components.
  //  * @param {!Blockly.Block} containerBlock Root block in mutator.
  //  * @this {Blockly.Block}
  //  */
  // compose: function (containerBlock) {
  //   console.log('compose')
  //   var itemBlock = containerBlock.getInputTargetBlock('STACK')
  //   // Count number of inputs.
  //   var connections = []
  //   while (itemBlock) {
  //     console.log('itemBlock1111', itemBlock, itemBlock.type)
  //     connections.push(itemBlock.valueConnection_)
  //     itemBlock = itemBlock.nextConnection &&
  //       itemBlock.nextConnection.targetBlock()
  //   }
  //   // Disconnect any children that don't belong.
  //   for (let i = 0; i < this.itemCount_; i++) {
  //     var connection = this.getInput('ADD' + i).connection.targetConnection
  //     if (connection && connections.indexOf(connection) === -1) {
  //       connection.disconnect()
  //     }
  //   }
  //   this.itemCount_ = connections.length
  //   this.updateShape_()
  //   // Reconnect any child blocks.
  //   for (let i = 0; i < this.itemCount_; i++) {
  //     Blockly.Mutator.reconnect(connections[i], this, 'ADD' + i)
  //   }
  // },
  // /**
  //  * Store pointers to any connected child blocks.
  //  * @param {!Blockly.Block} containerBlock Root block in mutator.
  //  * @this {Blockly.Block}
  //  */
  // saveConnections: function (containerBlock) {
  //   var itemBlock = containerBlock.getInputTargetBlock('STACK')
  //   var i = 0
  //   while (itemBlock) {
  //     var input = this.getInput('ADD' + i)
  //     itemBlock.valueConnection_ = input && input.connection.targetConnection
  //     i++
  //     itemBlock = itemBlock.nextConnection &&
  //       itemBlock.nextConnection.targetBlock()
  //     console.log('itemBlocksave', itemBlock)
  //   }
  // },
  /**
   * Modify this block to have the correct number of inputs.
   * @private
   * @this {Blockly.Block}
   */
  updateShape_: function () {
    // Add new inputs.
    for (var i = 0; i < this.itemCount_; i++) {
      if (!this.getInput('ADD' + i)) {
        var input = this.appendValueInput('ADD' + i)
        if (i === 0) {
          input.appendField('参数')
        }
        input.appendField(this.params[i]?.alias, 'param_alias')
      } else {
        const inputOld = this.getInput('ADD' + i)
        inputOld.removeField('param_alias')
        inputOld.appendField(this.params[i]?.alias, 'param_alias')
      }
    }
    // Remove deleted inputs.
    while (this.getInput('ADD' + i)) {
      this.removeInput('ADD' + i)
      i++
    }
  }
}

const helpFun = function () {
  // Initialize the mutator values.
  this.itemCount_ = 0
  this.params = []
  this.updateShape_()
  // this.setMutator(new Blockly.Mutator(['param_create_join_item']))
}
Blockly.Extensions.registerMutator('component_dispatch_mutator',
  mixinObj, helpFun)

// 生成js
Blockly.JavaScript['component_dispatch'] = function (block) {
  // 组件名
  const compVar = block.getFieldValue('Component')
  const funVar = block.getFieldValue('Function')

  var elements = new Array(block.itemCount_)
  for (var i = 0; i < block.itemCount_; i++) {
    elements[i] = Blockly.JavaScript.valueToCode(block, 'ADD' + i,
      Blockly.JavaScript.ORDER_COMMA) || '\'\''
  }
  var params = elements.join(', ')
  if (params.length) {
    params = ', ' + params
  }
  const code = `context.getComponent('${compVar}').dispatch('${funVar}'${params})\n`
  return code
}

// 3 ----- 获取组件实例的方法 ---不用
const selectJson = {
  type: 'component_select',
  'message0': '调用组件 %1 方法 %2  %3',
  args0: [
    // 动态生成选项
    {
      'type': 'input_dummy',
      'name': 'COMPONENT_INPUT'
    },
    {
      'type': 'input_dummy',
      'name': 'FUNC_INPUT'
    },
    {
      'type': 'input_dummy',
      'name': 'PARAM_INPUT'
    }
  ],
  extensions: ['dynamic_component_extension', 'dynamic_func_extension'],
  // previousStatement: null,
  // nextStatement: null,
  inputsInline: true,
  output: null,
  style: 'component_blocks',
  tooltip: '',
  helpUrl: '',
  mutator: 'component_dispatch_mutator'
}
// 创建积木
Blockly.Blocks['component_select'] = {
  init: function () {
    this.jsonInit(selectJson)
  }
}

// 生成js
Blockly.JavaScript['component_select'] = function (block) {
  // 组件名
  const compVar = block.getFieldValue('Component')
  const funVar = block.getFieldValue('Function')

  var elements = new Array(block.itemCount_)
  for (var i = 0; i < block.itemCount_; i++) {
    elements[i] = Blockly.JavaScript.valueToCode(block, 'ADD' + i,
      Blockly.JavaScript.ORDER_FUNCTION_CALL) || '\'\''
  }
  var params = elements.join(', ')
  const code = `context.getComponent('${compVar}').${funVar}(${params})`
  if (block.outputConnection) {
    return [code, Blockly.JavaScript.ORDER_FUNCTION_CALL]
  } else {
    return code + '\n'
  }
}

// 4 ----- 获取窗口组件实例的方法 ---- 不用
Blockly.Extensions.register('dynamic_modal_component_extension',
  function () {
    var that = this
    const dropdown = new Blockly.FieldDropdown(
      function () {
        var options = []
        // 组件previousStatement
        // const comList = store.getters.getFormList
        // todo 获取modal中的组件，，这是我乱写的
        const modal = store.getters.getFormData?.template || []
        const comList = modal.length ? modal[0]?.formList || [] : []
        if (!comList.length) {
          options = [['没有数据', 'noData']]
          return options
        }
        for (var i = 0; i < comList.length; i++) {
          const com = comList[i]
          const label = com?.__config?.label || ''
          var dateString = com.name + label + '（' + com.key + '）'
          options.push([dateString, com.key])
        }
        return options
      })
    if (this.getInput('FUNC_INPUT')) {
      dropdown.setValidator(function (value) {
        if (that.getInput('PARAM_INPUT')) {
          that.removeInput('PARAM_INPUT', true)
        }
        that.removeInput('FUNC_INPUT', true)
        that.appendDummyInput('FUNC_INPUT').appendField('方法')
        that.itemCount_ = 0
        that.updateShape_()
        Blockly.Extensions.apply('dynamic_modal_func_extension', that, false)
      })
    }
    this.getInput('COMPONENT_INPUT').appendField(dropdown, 'Component')
  })
Blockly.Extensions.register('dynamic_modal_func_extension',
  function () {
    var that = this
    const dropdown = new Blockly.FieldDropdown(
      function () {
        var options = []
        // 获取component的选择框的值
        // const list = store.getters.getFormList
        // 获取组件的值，Component extension中的值
        const compVar = that.getFieldValue('Component') // 组件的key
        if (!compVar || compVar === 'noData') {
          options = [['没有数据', 'noData']]
          return options
        }
        // todo 这里的组件获取能否方法统一获取所有
        const modal = store.getters.getFormData?.template || []
        const comList = modal.length ? modal[0]?.formList || [] : []
        // const comList = store.getters.getFormList
        const com = comList.find(item => item.key === compVar)
        const comType = com.tagName
        const config = componentFuncConfig[comType] || commonConfig
        for (var i = 0; i < config.length; i++) {
          var item = config[i]
          options.push([`${item.alias}(${item.key})`, item.key])
        }
        return options
      })
    dropdown.setValidator(function (value) {
      const oldValue = that.getFieldValue('Function')
      const compVar = that.getFieldValue('Component') // 组件的key、
      // todo 这里要修改  componentlist的数据
      const modal = store.getters.getFormData?.template || []
      const componentList = modal.length ? modal[0]?.formList || [] : []

      const com = componentList.find(item => item.key === compVar)
      if (!com) return
      const comType = com.tagName
      const config = componentFuncConfig[comType] // 组件的配置
      const funcConfig = config?.find(item => item.key === value)
      const oldConfig = config?.find(item => item.key === oldValue)
      const hasReturn = funcConfig && !!funcConfig.hasReturn
      const oldHasReturn = oldConfig && !!oldConfig.hasReturn
      if (that?.previousConnection?.targetConnection && hasReturn !== oldHasReturn && oldValue !== value) {
        Message({
          message: '该选项不支持当前连接，前先断开连接再选择',
          type: 'warning'
        })
        return null
      }

      // 参数的判断
      const params = funcConfig?.params || []
      that.params = params
      if (!params?.length) {
        that.itemCount_ = 0
        that.updateShape_()
      } else {
        that.itemCount_ = params.length
        that.updateShape_()
      }

      // // 设置有没有函数体
      if (hasReturn) {
        that.setPreviousStatement(false)
        that.setNextStatement(false)
        that.setOutput(true, null)
      } else {
        that.setOutput(false, null)
        that.setPreviousStatement(true)
        that.setNextStatement(true)
      }
      // that.setStatements_(statement)
    })
    // 生成extension的block
    if (!this.getInput('Function')) {
      this.getInput('FUNC_INPUT')
        .appendField(dropdown, 'Function')
    }
  })
const modalJson = {
  type: 'modal_component_select',
  'message0': '调用窗口中组件 %1 方法 %2  %3',
  args0: [
    // 动态生成选项
    {
      'type': 'input_dummy',
      'name': 'COMPONENT_INPUT'
    },
    {
      'type': 'input_dummy',
      'name': 'FUNC_INPUT'
    },
    {
      'type': 'input_dummy',
      'name': 'PARAM_INPUT'
    }
  ],
  extensions: ['dynamic_modal_component_extension', 'dynamic_modal_func_extension'],
  // previousStatement: null,
  // nextStatement: null,
  inputsInline: true,
  output: null,
  style: 'component_blocks',
  tooltip: '',
  helpUrl: '',
  mutator: 'component_dispatch_mutator'
}

// 创建积木
Blockly.Blocks['modal_component_select'] = {
  init: function () {
    this.jsonInit(modalJson)
  }
}
// 生成js
Blockly.JavaScript['modal_component_select'] = function (block) {
  let context = 'context'
  const parent = findParentByType(block, 'callback_function_expression')
  const openModal = findParentByType(block, 'open_modal')
  if (parent && openModal) {
    if (parent.itemCount_ > 0) {
      const block = parent.getInputTargetBlock('ADD0')
      if (block) {
        context = Blockly.JavaScript.valueToCode(parent, 'ADD0',
          Blockly.JavaScript.ORDER_COMMA)
      }
    }
  }
  // 组件名
  const compVar = block.getFieldValue('Component')
  const funVar = block.getFieldValue('Function')

  var elements = new Array(block.itemCount_)
  for (var i = 0; i < block.itemCount_; i++) {
    elements[i] = Blockly.JavaScript.valueToCode(block, 'ADD' + i,
      Blockly.JavaScript.ORDER_COMMA) || '\'\''
  }

  // 调用的主体不一定是tctx, pc弹窗的回调函数时不是context
  var params = elements.join(', ')
  const code = `${context}.getComponent('${compVar}').${funVar}(${params})`
  if (block.outputConnection) {
    return [code, Blockly.JavaScript.ORDER_COMMA]
  } else {
    return code + '\n'
  }
}

//  5------------------- 组件显示隐藏------------------------------------------------
const showJson = {
  type: 'component_display',
  message0: '%1 %2组件',
  args0: [
    // 动态生成选项
    {
      'type': 'field_label_serializable',
      'name': 'DISPLAY_TYPE',
      'text': '显示'
    },
    {
      'type': 'input_dummy',
      'name': 'COMPONENT_INPUT'
    }
  ],
  extensions: ['dynamic_component_extension'],
  previousStatement: null,
  nextStatement: null,
  inputsInline: true,
  style: 'action_blocks',
  tooltip: '',
  helpUrl: ''
}
// 创建积木
Blockly.Blocks['component_display'] = {
  init: function () {
    this.jsonInit(showJson)
  }
}
Blockly.JavaScript['component_display'] = function (block) {
  const compVar = block.getFieldValue('Component')
  const context = getContextText(block, compVar)
  const flag = block.getFieldValue('DISPLAY_TYPE') === '隐藏'
  const code = `${context}.getComponent('${compVar}').dispatch('setConfig',{visible: ${flag}})\n`
  return code
}

//  6------------------- 组件启用禁用------------------------------------------------
const disableJson = {
  type: 'component_disable',
  message0: '%1 %2组件',
  args0: [
    // 动态生成选项
    {
      'type': 'field_label_serializable',
      'name': 'DISABLE_TYPE',
      'text': '启用'
    },
    {
      'type': 'input_dummy',
      'name': 'COMPONENT_INPUT'
    }
  ],
  extensions: ['dynamic_component_extension'],
  inputsInline: true,
  previousStatement: null,
  nextStatement: null,
  style: 'action_blocks',
  tooltip: '',
  helpUrl: ''
}
// 创建积木
Blockly.Blocks['component_disable'] = {
  init: function () {
    this.jsonInit(disableJson)
  }
}
Blockly.JavaScript['component_disable'] = function (block) {
  const compVar = block.getFieldValue('Component')
  const context = getContextText(block, compVar)
  const flag = block.getFieldValue('DISABLE_TYPE') === '禁用'
  const code = `${context}.getComponent('${compVar}').dispatch('setConfig',{disabled : ${flag}})\n`
  return code
}

//  6------------------- 组件必填非必填------------------------------------------------
const requiredJson = {
  type: 'component_required',
  message0: '组件 %1 %2',
  args0: [
    // 动态生成选项
    {
      'type': 'input_dummy',
      'name': 'COMPONENT_INPUT'
    },
    {
      'type': 'field_label_serializable',
      'name': 'REQUIRED_TYPE',
      'text': '设为必填'
    }
  ],
  extensions: ['dynamic_component_extension'],
  previousStatement: null,
  nextStatement: null,
  inputsInline: true,
  style: 'action_blocks',
  tooltip: '',
  helpUrl: ''
}
// 创建积木
Blockly.Blocks['component_required'] = {
  init: function () {
    this.jsonInit(requiredJson)
  }
}
Blockly.JavaScript['component_required'] = function (block) {
  const compVar = block.getFieldValue('Component')
  const context = getContextText(block, compVar)
  const flag = block.getFieldValue('REQUIRED_TYPE') === '设为必填'
  const code = `${context}.getComponent('${compVar}').dispatch('setConfig',{required : ${flag}})\n`
  return code
}
